# @Time    : 2024/2/7 23:37
# @Author  : 🍁
# @File    : cos.py
# @Software: PyCharm
from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
from django.conf import settings
from sts.sts import Sts
from qcloud_cos.cos_exception import CosServiceError


# 新建桶
def create_bucket(bucket, region="ap-beijing"):
    """
    创建桶
    :param bucket: 桶的名称
    :param region: 区域
    :return:
    """
    tmp_secret_id = settings.TENCENT_COS_ID  # 临时密钥的 SecretId，临时密钥生成和使用指引参见 https://cloud.tencent.com/document/product/436/14048
    tmp_secret_key = settings.TENCENT_COS_KEY  # 临时密钥的 SecretKey，临时密钥生成和使用指引参见 https://cloud.tencent.com/document/product/436/14048
    config = CosConfig(Region=region, SecretId=tmp_secret_id, SecretKey=tmp_secret_key)
    client = CosS3Client(config)
    response = client.create_bucket(
        Bucket=bucket,
        ACL="public-read",  # private / public-read / public-read-write
    )
    cors_config = {
        "CORSRule": [
            {
                "AllowedOrigin": "*",
                "AllowedMethod": ["GET", "POST", "PUT", "DELETE", "HEAD"],
                "AllowedHeader": "*",
                "ExposeHeader": ["*", "-meta-test1"],
                "MaxAgeSeconds": 500
            }
        ]
    }
    client.put_bucket_cors(
        Bucket=bucket,
        CORSConfiguration=cors_config
    )


# 上传文件
def upload_file(bucket, region, body, key):
    """
    上传图片
    :param bucket:  桶名
    :param region:  区域
    :param body:    上传的文件对象
    :param key:     上传到桶的文件名
    :return:        图片路径
    """
    tmp_secret_id = settings.TENCENT_COS_ID
    tmp_secret_key = settings.TENCENT_COS_KEY
    config = CosConfig(Region=region, SecretId=tmp_secret_id, SecretKey=tmp_secret_key)
    client = CosS3Client(config)
    #### 高级上传接口（推荐）
    # 根据文件大小自动选择简单上传或分块上传，分块上传具备断点续传功能。
    response = client.upload_file_from_buffer(
        Bucket=bucket,  # 桶名
        Body=body,  # 要上传的文件的对象
        Key=key,  # 上传到桶之后的文件名
    )

    return "https://{0}.cos.{1}.myqcloud.com/{2}".format(bucket, region, key)


# 删除文件
def delete_file(bucket, region, file_list):
    """
    删除文件
    :param bucket: 桶名
    :param region: 区域
    :param file_list: 上传到桶的文件名
    :return:
    """
    tmp_secret_id = settings.TENCENT_COS_ID
    tmp_secret_key = settings.TENCENT_COS_KEY
    config = CosConfig(Region=region, SecretId=tmp_secret_id, SecretKey=tmp_secret_key)
    client = CosS3Client(config)

    objects = {
        "Quiet": "true",
        "Object": [{"Key": key} for key in file_list]
    }
    #### 高级上传接口（推荐）
    # 根据文件大小自动选择简单上传或分块上传，分块上传具备断点续传功能。
    response = client.delete_objects(

        Bucket=bucket,  # 桶名
        Delete=objects,  # 上传到桶之后的文件名
    )


# 获取临时凭证
def credential(bucket, region):
    """
    获取临时凭证
    :param bucket: 桶名
    :param region: 区域
    :return: 临时凭证的字典
    """
    config = {
        # 临时密钥有效时长，单位是秒（30分钟=1800秒）
        'duration_seconds': 1800,
        # 固定密钥 id
        'secret_id': settings.TENCENT_COS_ID,
        # 固定密钥 key
        'secret_key': settings.TENCENT_COS_KEY,
        # 换成你的 bucket
        'bucket': bucket,
        # 换成 bucket 所在地区
        'region': region,
        # 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的具体路径
        # 例子： a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用)
        'allow_prefix': '*',
        # 密钥的权限列表。简单上传和分片需要以下的权限，其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
        'allow_actions': [
            # 'name/cos:PostObject',
            # 'name/cos:DeleteObject',
            # "name/cos:UploadPart",
            # "name/cos:UploadPartCopy",
            # "name/cos:CompleteMultipartUpload",
            # "name/cos:AbortMultipartUpload",
            "*",
        ],

    }
    sts = Sts(config)
    result_dict = sts.get_credential()
    return result_dict


# 用来判断文件是否合法
def check_file(bucket, region, key):
    """
    用来判断文件是否合法
    :param bucket: 桶名
    :param region: 区域
    :param key: 储存到桶的文件名
    :return: 该文件存储到桶的一些数据
    """
    tmp_secret_id = settings.TENCENT_COS_ID
    tmp_secret_key = settings.TENCENT_COS_KEY
    config = CosConfig(Region=region, SecretId=tmp_secret_id, SecretKey=tmp_secret_key)
    client = CosS3Client(config)

    data = client.head_object(
        Bucket=bucket,
        Key=key
    )
    return data


def delete_bucket(bucket, region):
    """
    删除桶
    :param bucket: 桶名
    :param region: 区域
    :return:
    """
    tmp_secret_id = settings.TENCENT_COS_ID
    tmp_secret_key = settings.TENCENT_COS_KEY
    config = CosConfig(Region=region, SecretId=tmp_secret_id, SecretKey=tmp_secret_key)
    client = CosS3Client(config)

    try:
        # 查询到桶中的所有文件
        while True:
            # 获取桶中所有文件，一次最多获取1000个文件
            file_list = client.list_buckets(bucket)

            # file_list.get("Contents") 获取文件对象列表
            contents = file_list.get("Contents")
            if not contents:  # 如果获取文件列表为空，跳出循环
                break
            file_dict = [{"Key": file["Key"]} for file in contents]
            objects = {
                "Quiet": "true",
                "Object": file_dict
            }
            # 删除文件
            client.delete_objects(
                Bucket=bucket,
                Delete=objects
            )
        # 查询到桶中的所有碎片
        while True:
            # 获取桶中的所有碎片，一次最多1000个
            part_uploads = client.list_multipart_uploads(Bucket=bucket)
            # 获取所有碎片对象
            upload = part_uploads.get("Upload")
            if not upload:  # 如果碎片对象为空，跳出循环
                break
            for item in upload:  # 删除碎片
                client.abort_multipart_upload(
                    Bucket=bucket,
                    Key=item["Key"],
                    UploadId=item["UploadId"]
                )
        # 删除桶
        client.delete_bucket(bucket)
    except CosServiceError as e:
        pass
